/**
 * @(#) HessianServiceManager.java
 * module  : RemotingCallFramework
 * version : 版本管理系统中的文件版本
 * date    : 2008-12-3
 * name    : 马仁配
 */
package com.smartpay.its.framework.remoting.hessian.server.impl;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cglib.proxy.Factory;
import org.springframework.remoting.caucho.HessianServiceExporter;

import com.smartpay.its.framework.remoting.hessian.server.HessianService;
import com.smartpay.its.framework.remoting.hessian.server.IHessianServiceManager;

/**
 * Hessian服务管理器
 */
public class HessianServiceManager implements IHessianServiceManager {
	
	private static final Logger logger = LoggerFactory.getLogger(HessianServiceManager.class);
	/**
	 * 所有注册的hessian服务.
	 */
	private Map<String, HessianService> services = new HashMap<String, HessianService>();

	/**
	 * HessianServiceExporter的缓存,避免每次访问都实例化exporter.
	 */
	private Map<String, HessianServiceExporter> exporters = new HashMap<String, HessianServiceExporter>();

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.smartpay.rcf.hessian.server.IHessianServiceManager#registerService
	 * (java.lang.Object)
	 */
	public void registerService(Object obj) {
		// 使用第一个接口作为发布出去的hessian服务接口.
		Class<?>[] clazz = obj.getClass().getInterfaces();
		// 如果在当前类上没有实现接口,则取父类实现的第一个接口.
		// 契约:要发布为hessian服务的类或父类必须要实现一个服务接口.
		if (null == clazz || clazz.length == 0) {
			clazz = obj.getClass().getSuperclass().getInterfaces();
		}
		Class<?> inf = clazz[0];
		HessianService service = new HessianService(inf, obj);
		services.put(inf.getName(), service);
		logger.info("registed hessian service:" + inf.getName());
	}
	
	/**
	 * hessian 注册
	 * @param str 接口实现 （包名+类名）
	 * @param obj2 接口实现
	 */
	public void registerService(final String str,Object obj2) {
		//获取所有接口
		Class<?>[] clazzs = null;
		Class _clazz =null;
		try {
		//比较所传入的接口与实现相匹配
			_clazz = this.getClass().forName(str);//实现
			clazzs = _clazz.getInterfaces();
			Class<?> clazz = clazzs[0];//接口
			HessianService service = new HessianService(clazz, _clazz.cast(obj2));
			services.put(clazz.getName(), service);			
			logger.info("registed hessian service name:" + clazz.getName());
		} catch (ClassNotFoundException e) {
			logger.error("Class is not Found: "+str);
		} catch (Exception e){
			logger.error("Not registed hessian service name:" +str);
		}			
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.smartpay.rcf.hessian.server.IHessianServiceManager#registerServices
	 * (java.util.List)
	 */
	public void registerServices(List<Object> objects) {
		if (null != objects) {
			Iterator<Object> it = objects.iterator();
			while (it.hasNext()) {
				registerService(it.next());
			}
		}
	}
	
	public void registerServices(Map<String,Object> objects) {
		if (null != objects) {
			Iterator<Entry<String, Object>> it = objects.entrySet().iterator();
			while (it.hasNext()) {
				Entry<String, Object> o = it.next();
				registerService(o.getKey(),o.getValue());
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.smartpay.bundles.common.hessianservicebundle.service.
	 * IHessianServiceManager
	 * #unregisterService(com.cbireport.bundles.common.hessianservicebundle
	 * .service.HessianService)
	 */
	public void unregisterService(HessianService service) {
		String name = service.getServiceInterface().getName();
		exporters.remove(name);
		services.remove(name);
		logger.info("unregisted hessian service:" + name);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.smartpay.bundles.common.hessianservicebundle.service.
	 * IHessianServiceManager#findService(java.lang.String)
	 */
	public HessianServiceExporter findService(String serviceId) {
		HessianServiceExporter exporter = exporters.get(serviceId);
		// 取缓存,没有则创建,这样可以减少启动时间.
		if (null == exporter) {
			exporter = createExporter(serviceId);
		}
		return exporter;
	}

	/**
	 * 根据参数serviceId从services容器中取到hessian服务,然后创建一个HessianServiceExporter
	 * 并把创建的对象放到exporter容器中,然后返回这个对象.
	 * 
	 * @param serviceId
	 * @return
	 */
	protected HessianServiceExporter createExporter(String serviceId) {
		HessianServiceExporter exporter = new HessianServiceExporter();
		HessianService service = services.get(serviceId);
		if (null == service) {
			return null;
		}
		exporter.setService(service.getServiceBean());
		exporter.setServiceInterface(service.getServiceInterface());
		exporter.afterPropertiesSet();
		exporters.put(serviceId, exporter);
		return exporter;
	}
}
